package com.yupi.springbootinit.service.impl;

import com.yupi.springbootinit.mapper.NumberSequenceMapper;
import com.yupi.springbootinit.model.entity.NumberSequence;
import com.yupi.springbootinit.service.BatchCodeGeneratorService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import net.sourceforge.pinyin4j.PinyinHelper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * 批次编码生成服务实现
 *
 * @author yupi
 */
@Slf4j
@Service
public class BatchCodeGeneratorServiceImpl implements BatchCodeGeneratorService {

    /**
     * 日期格式化器（yyMMdd）
     */
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyMMdd");

    /**
     * 默认产品代号（无法识别时使用）
     */
    private static final String DEFAULT_PRODUCT_CODE = "UNKN";

    @Resource
    private NumberSequenceMapper numberSequenceMapper;



    @Override
    public String generateProductCode(String productName) {
        if (StringUtils.isBlank(productName)) {
            log.warn("产品名称为空，返回默认代号: {}", DEFAULT_PRODUCT_CODE);
            return DEFAULT_PRODUCT_CODE;
        }

        // 1. 提取中文汉字
        String cleanName = productName.replaceAll("[^\\u4e00-\\u9fa5]", "");

        // 如果没有中文，处理纯英文/数字情况
        if (cleanName.isEmpty()) {
            String result = productName.replaceAll("[^a-zA-Z0-9]", "")
                    .toUpperCase();
            // 如果长度小于4，末尾补1
            if (result.length() < 4) {
                result += "1";
            }
            // 截取前4位
            if (result.length() > 4) {
                result = result.substring(0, 4);
            }
            return StringUtils.isNotBlank(result) ? result : DEFAULT_PRODUCT_CODE;
        }

        // 2. 转换拼音首字母
        StringBuilder code = new StringBuilder();
        for (char c : cleanName.toCharArray()) {
            try {
                String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(c);
                if (pinyinArray != null && pinyinArray.length > 0) {
                    code.append(Character.toUpperCase(pinyinArray[0].charAt(0)));
                }
            } catch (Exception e) {
                // 忽略无法转换的字符
            }
        }

        String result = code.toString();

        // 3. 【修改】符合新规则：若原始产品名称少于四个字，则在首拼音字号后加1
        // 这里判断的是原始中文汉字的长度
        if (cleanName.length() < 4) {
            result += "1";
        }

        // 4. 限制长度最多4位 (例如：测试产品五 -> CSCPW -> CSCP)
        if (result.length() > 4) {
            result = result.substring(0, 4);
        }

        return result;
    }

    @Override
    public String generateBatchCode(String productName, String deviceCode, Integer batchNo) {
        // 1. 产品代号
        String productCode = generateProductCode(productName);

        // 2. 日期+机台号：yyMMdd + 设备编码（两位）
        LocalDateTime now = LocalDateTime.now();
        String datePart = now.format(DATE_FORMATTER);

        // 设备编码补零到两位
        String devicePart = StringUtils.leftPad(
                StringUtils.defaultString(deviceCode, "00"),
                2,
                '0'
        );

        // 3. 版本号：批次序号转字母（1→A, 2→B, 3→C...）
        int index = (batchNo != null && batchNo > 0) ? (batchNo - 1) : 0;
        String versionPart = toAlphaCode(index);

        // 4. 拼接完整编码
        String batchCode = productCode + "-" + datePart + devicePart + "-" + versionPart;

        log.info("✅ 批次编码生成: productName={}, deviceCode={}, batchNo={} → {}",
                productName, deviceCode, batchNo, batchCode);

        return batchCode;
    }

    @Override
    public String buildFullProcessSheetNo(String baseNo, String version) {
        if (StringUtils.isBlank(baseNo)) {
            log.warn("工艺单基础号为空");
            return "";
        }

        String ver = StringUtils.isNotBlank(version) ? version : "A";
        String fullNo = baseNo + "-" + ver;

        log.debug("完整工艺单号: {} + {} → {}", baseNo, ver, fullNo);

        return fullNo;
    }

    @Override
    public String toAlphaCode(int index) {
        if (index < 0) {
            log.warn("索引不能为负数: {}, 使用0", index);
            index = 0;
        }

        StringBuilder sb = new StringBuilder();
        int i = index;

        do {
            int rem = i % 26;
            sb.insert(0, (char) ('A' + rem));
            i = i / 26 - 1;
        } while (i >= 0);

        String result = sb.toString();
        log.debug("数字转字母: {} → {}", index, result);

        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized String generateFlowNumber() {
        LocalDate today = LocalDate.now();
        String dateStr = today.format(DateTimeFormatter.ofPattern("yyMMdd"));

        log.info("开始生成流程卡编号: date={}", today);

        // 查询或创建今日流水号记录（加行锁）
        NumberSequence seq = numberSequenceMapper.selectForUpdate("FLOW_NUMBER", today);

        int nextSeq;
        if (seq == null) {
            // 当天首次生成
            seq = new NumberSequence();
            seq.setBusinessType("FLOW_NUMBER");
            seq.setDate(today);
            seq.setCurrentSequence(1);
            numberSequenceMapper.insert(seq);
            nextSeq = 1;

            log.info("创建新的流水号记录: date={}, sequence=1", today);
        } else {
            // 递增
            nextSeq = seq.getCurrentSequence() + 1;
            seq.setCurrentSequence(nextSeq);
            numberSequenceMapper.updateById(seq);

            log.debug("流水号递增: date={}, sequence={}", today, nextSeq);
        }

        // 格式化：YYMMDD + 02d（两位流水号）
        String flowNumber = dateStr + String.format("%02d", nextSeq);

        log.info("✅ 流程卡编号生成成功: date={}, sequence={}, flowNumber={}",
                today, nextSeq, flowNumber);

        return flowNumber;
    }
}